package com.ray.finance.strategy.bill.goods;

import cn.hutool.core.util.ObjectUtil;
import com.ray.base.service.BaseCustomerService;
import com.ray.base.service.compose.GoodsService;
import com.ray.base.table.vo.material.model.MaterialModelVO;
import com.ray.business.builder.PurchaseGoodsBuilder;
import com.ray.business.service.*;
import com.ray.business.service.compose.BusinessService;
import com.ray.business.service.compose.PurcahseService;
import com.ray.business.service.compose.SaleService;
import com.ray.business.table.entity.ProdPurchase;
import com.ray.business.table.entity.ProdPurchaseBackRecord;
import com.ray.business.table.entity.ProdPurchaseIn;
import com.ray.business.table.entity.ProdPurchaseInRecord;
import com.ray.business.table.vo.PurchaseGoodsVO;
import com.ray.finance.api.BillAdjustApi;
import com.ray.finance.builder.BillBuilder;
import com.ray.finance.enums.BillStatusEnum;
import com.ray.finance.service.FinaBillAdjustService;
import com.ray.finance.service.FinaBillPayService;
import com.ray.finance.service.FinaBillService;
import com.ray.finance.service.compose.AdvanceService;
import com.ray.finance.table.entity.FinaBill;
import com.ray.finance.table.params.bill.BillCreateParams;
import com.ray.magicBlock.BlockDispatch;
import com.ray.magicBlock.Strategy;
import com.ray.magicBlock.anno.Block;
import com.ray.woodencreate.beans.LoginUser;
import com.ray.woodencreate.exception.BusinessExceptionFactory;
import com.ray.woodencreate.result.MsgCodeConstant;
import com.ray.woodencreate.result.Result;
import com.ray.woodencreate.result.ResultFactory;
import com.ray.woodencreate.util.LogInUserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author bo shen
 * @Description: 对账单
 * @Class: PurchaseInService
 * @Package com.ray.wms.strategy.in
 * @date 2020/6/8 15:05
 * @company <p>Ray快速开发平台</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Slf4j
@Block(group = "goodsList", strategy = "PURCHASE", desc = "采购对账单商品明细")
public class PurchaseGoodsService implements Strategy<String, LoginUser, List<?>> {


    @Autowired
    private ProdPurchaseInRecordService prodPurchaseInRecordService;
    @Autowired
    private ProdPurchaseInService prodPurchaseInService;
    @Autowired
    private ProdPurchaseBackRecordService prodPurchaseBackRecordService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private ProdPurchaseService prodPurchaseService;


    @Override
    public List<?> execute(String billNo, LoginUser loginUser) {
        //查询对账单对应的订单
        List<String> orderNOs = prodPurchaseService.queryPurchaseByBIllNo(billNo, loginUser).stream().map(ProdPurchase::getOrderNo).collect(Collectors.toList());
        BillCreateParams billCreateParams = new BillCreateParams();
        billCreateParams.setOrderNos(orderNOs);
        return pruchaseGoodsList(billCreateParams);
    }


    /**
     * 采购单明细
     *
     * @param createParams
     * @return
     */
    public List<PurchaseGoodsVO> pruchaseGoodsList(@Valid BillCreateParams createParams) {
        //当前登录对象
        LoginUser loginUser = LogInUserUtil.get();
        //查询采购单列表
        List<String> orderNos = createParams.getOrderNos();
        if (ObjectUtil.isEmpty(orderNos)) {
            return new ArrayList<>();
        }
        Map<String, ProdPurchaseInRecord> inRecordMap = new HashMap<>();
        //查询完成的订单
        List<String> finishNos = prodPurchaseInService.listFinishByOrderNos(orderNos, loginUser).stream().map(ProdPurchaseIn::getInCode).collect(Collectors.toList());
        //入库数据
        List<ProdPurchaseInRecord> records = prodPurchaseInRecordService.listByInCodes(finishNos, loginUser);
        //处理数据
        records.forEach(prodPurchaseInRecord -> {
            String key = String.format("%s_%s", prodPurchaseInRecord.getOrderNo(), prodPurchaseInRecord.getGoodsCode());
            ProdPurchaseInRecord inRecord = inRecordMap.get(key);
            if (ObjectUtil.isNull(inRecord)) {
                inRecordMap.put(key, prodPurchaseInRecord);
            } else {
                inRecord.setQuantity(inRecord.getQuantity().add(prodPurchaseInRecord.getQuantity()));
                inRecord.setTotal(inRecord.getTotal() + prodPurchaseInRecord.getTotal());
            }
        });
        //退货数据
        List<ProdPurchaseBackRecord> backRecords = prodPurchaseBackRecordService.listByOrderNo(orderNos, loginUser);
        //处理数据
        backRecords.forEach(prodPurchaseBackRecord -> {
            String key = String.format("%s_%s", prodPurchaseBackRecord.getOrderNo(), prodPurchaseBackRecord.getGoodsCode());
            ProdPurchaseInRecord inRecord = inRecordMap.get(key);
            if (ObjectUtil.isNotNull(inRecord)) {
                inRecord.setQuantity(inRecord.getQuantity().subtract(prodPurchaseBackRecord.getQuantity()));
                inRecord.setTotal(inRecord.getTotal() - (prodPurchaseBackRecord.getTotal()));
            }
        });

        final List<BigDecimal> quantity = new ArrayList<>();
        Map<String, MaterialModelVO> modelMap = new HashMap<>();
        final List<BigDecimal> totalPriceList = new ArrayList<>();
        List<PurchaseGoodsVO> purchaseGoodsVOS = inRecordMap.values().stream().map(prodPurchaseRecord -> {
            MaterialModelVO materialModelVO = modelMap.get(prodPurchaseRecord.getGoodsCode());
            if (ObjectUtil.isNull(materialModelVO)) {
                materialModelVO = goodsService.queryGoodsByCode(prodPurchaseRecord.getGoodsCode(), loginUser);
                modelMap.put(prodPurchaseRecord.getGoodsCode(), materialModelVO);
            }
            quantity.add(prodPurchaseRecord.getQuantity());
            totalPriceList.add(prodPurchaseRecord.getQuantity().multiply(prodPurchaseRecord.getPrice()));
            return new PurchaseGoodsBuilder().append(prodPurchaseRecord).append(materialModelVO)
                    .appendTotalAmount(prodPurchaseRecord.getQuantity().multiply(prodPurchaseRecord.getPrice())).bulid();
        }).collect(Collectors.toList());
        //计算总价
        PurchaseGoodsVO purchaseGoodsVO = new PurchaseGoodsVO();
        purchaseGoodsVO.setBizCode("合计:");
        purchaseGoodsVO.setTotalAmount(totalPriceList.stream().reduce(BigDecimal::add).get());
        purchaseGoodsVO.setQuantity(quantity.stream().reduce(BigDecimal::add).get());
        purchaseGoodsVOS.add(purchaseGoodsVO);
        return purchaseGoodsVOS;
    }
}
